package zmee.entity;

import com.kingdee.bos.qing.util.MapUtils;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.util.CollectionUtils;

import java.util.*;

/**
 * @author yss
 * @createTime 2022-12-21 15:16
 * @description 预算项目实体类
 */
public class BudgetProInfo {

    /** 项目id */
    private Long proId;
    /** 年度 预算生效id */
    private Map<Integer,Set<Long>> budgetYearValidMap;
    /** 生效id可追溯上游id集合 */
    private Map<Long,Set<Long>> validParentSetMap;
    /** 生效id可追溯所有上游id集合 */
    private Map<Long,Set<Long>> validAllParentSetMap;
    /** 设置预算信息时，存在的可追溯上游id集合 */
    private Set<Long> validParentSetOfSet;

    public BudgetProInfo(Long proId){
        setProId(proId);
        setBudgetInfo();
    }

    public void setProId(Long proId) {
        this.proId = proId;
    }

    /**
     * 设置 年度 预算生效id
     */
    public void setBudgetYearValidMap(Integer year,Long parentId){
        this.budgetYearValidMap = setLongAndSetMap(year,parentId,getBudgetYearValidMap());
    }

    /**
     * 设置生效id可追溯上游id集合
     * @param validId
     * @param parentId
     */
    public void setValidParentSetMap(Long validId,Long parentId) {
        this.validParentSetMap = setLongAndSetMap(validId,parentId,getValidParentSetMap());
    }
    /**
     * 设置存在的所有可追溯上游id集合
     * @param validId
     * @param parentId
     */
    public void setValidAllParentSetMap(Long validId,Long parentId){
        this.validAllParentSetMap = setLongAndSetMap(validId,parentId,getValidAllParentSetMap());
    }

    /**
     * 设置项目预算信息
     */
    public void setBudgetInfo(){
        Set<Long> parentSet = this.validParentSetOfSet;
        this.validParentSetOfSet = null;
        //根据项目id获取项目下所有的预算信息
        QFilter qFilter = new QFilter("billstatus", QCP.equals,"C");
        QFilter outBudgetProjectQFilter = new QFilter("project.id", QCP.equals, proId);
        QFilter outBudgetIsvalidQFilter = new QFilter("isvalid",QCP.equals,true);
        QFilter outBudgetTreeentryentityQFilter = new QFilter("treeentryentity.id",QCP.in,parentSet);
        boolean hasAdjust = CollectionUtils.isNotEmpty(parentSet);
        if(hasAdjust){//存在调整信息
            qFilter = qFilter.and(outBudgetTreeentryentityQFilter);
        }else {//不存在调整信息
            qFilter = qFilter.and(outBudgetProjectQFilter).and(outBudgetIsvalidQFilter);
        }
        String selectors = "year,treeentryentity,treeentryentity.projectbudgetitem parentid,treeentryentity.budgetitemname,isvalid";
        DynamicObjectCollection outBudgetDyCo = QueryServiceHelper.query("pmas_outbudget", selectors,new QFilter[]{qFilter});
        for(DynamicObject outBudgetDy : outBudgetDyCo){
            Date year = outBudgetDy.getDate("year");
            //当前id
            long budgetId = outBudgetDy.getLong("treeentryentity");
            long parentid = outBudgetDy.getLong("parentid");
            if(hasAdjust){
                Map<Long, Set<Long>> validAllParentSetMap = getValidAllParentSetMap();
                List<Long> allParentVaildList = getLongAndSetListKey(budgetId, validAllParentSetMap);
                for(Long parentVaild : allParentVaildList){
                    setValidAllParentSetMap(parentVaild,parentid);
                    //判断当前上游id是否存在上游id
                    List<Long> parentVaildList = getLongAndSetListKey(parentVaild, validAllParentSetMap);
                    if(CollectionUtils.isNotEmpty(parentVaildList) && parentVaildList.size() == 1){//不存在多个上游id
                        setValidParentSetMap(parentVaild,parentid);
                    }
                }
            }else {//不为调整单据
                setBudgetYearValidMap(getDateOfYear(year),budgetId);
                setValidAllParentSetMap(budgetId,budgetId);
                setValidAllParentSetMap(budgetId,parentid);
                setValidParentSetMap(budgetId,budgetId);
                setValidParentSetMap(budgetId,parentid);
            }
            if(budgetId != parentid){//存在上游单据
                setValidParentSetOfSet(parentid);
            }
        }
        if(CollectionUtils.isNotEmpty(this.validParentSetOfSet)){//存在上游单据
            setBudgetInfo();
        }
    }

    /**
     * 设置Map<Long, Set<Long>> map
     * @param key
     * @param value
     * @param map
     */
    public Map<Long, Set<Long>> setLongAndSetMap(Long key,Long value,Map<Long, Set<Long>> map){
        if(map == null){
            map = new HashMap<>();
        }
        if(map.containsKey(key)){
            Set<Long> mapSet = map.get(key);
            mapSet.add(value);
        }else {
            Set<Long> mapSet = new HashSet<>();
            mapSet.add(value);
            map.put(key,mapSet);
        }
        return map;
    }
    /**
     * 设置Map<Integer, Set<Long>> map
     * @param key
     * @param value
     * @param map
     */
    public Map<Integer, Set<Long>> setLongAndSetMap(Integer key,Long value,Map<Integer, Set<Long>> map){
        if(map == null){
            map = new HashMap<>();
        }
        if(map.containsKey(key)){
            Set<Long> mapSet = map.get(key);
            mapSet.add(value);
        }else {
            Set<Long> mapSet = new HashSet<>();
            mapSet.add(value);
            map.put(key,mapSet);
        }
        return map;
    }
    public void setValidParentSetOfSet(Long parentId){
        Set<Long> validParentSet = CollectionUtils.isEmpty(getValidParentSetOfSet()) ? new HashSet<>() : getValidParentSetOfSet();
        validParentSet.add(parentId);
        this.validParentSetOfSet = validParentSet;
    }
    /**
     * 根据value,获取Map<Long, Set<Long>> map型的key
     * @param value
     * @param map
     * @return
     */
    public Long getLongAndSetKey(Long value,Map<Long, Set<Long>> map){
        for(Map.Entry<Long, Set<Long>> entry : map.entrySet()){
            Set<Long> entryValue = entry.getValue();
            if(entryValue.contains(value)){
                return entry.getKey();
            }
        }
        return null;
    }
    /**
     * 根据value,获取Map<Long, Set<Long>> map型的所有key
     * @param value
     * @param map
     * @return
     */
    public List<Long> getLongAndSetListKey(Long value,Map<Long, Set<Long>> map){
        List<Long> listKey = new ArrayList<>();
        for(Map.Entry<Long, Set<Long>> entry : map.entrySet()){
            Set<Long> entryValue = entry.getValue();
            if(entryValue.contains(value)){
                listKey.add(entry.getKey());
            }
        }
        return listKey;
    }
    /**
     * 获取日期的年份
     * @param date
     * @return
     */
    public Integer getDateOfYear(Date date){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date == null ? new Date() : date);
        return calendar.get(Calendar.YEAR);
    }

    public Long getProId() {
        return proId;
    }
    public Map<Integer, Set<Long>> getBudgetYearValidMap() {
        return budgetYearValidMap;
    }
    public Map<Long, Set<Long>> getValidParentSetMap() {
        return validParentSetMap;
    }
    public Set<Long> getValidParentSetMap(Long budgetId) {
        Set<Long> budgetValidIdSet = MapUtils.isEmpty(validParentSetMap) ?  new HashSet<>() : validParentSetMap.get(budgetId);
        return budgetValidIdSet;
    }
    public Set<Long> getValidParentSetOfSet() {
        return validParentSetOfSet;
    }
    public Map<Long, Set<Long>> getValidAllParentSetMap() {
        return validAllParentSetMap;
    }
    public Set<Long> getValidAllParentSetMap(Long budgetId) {
        Set<Long> budgetValidIdSet = new HashSet<>();
        if(MapUtils.isEmpty(validAllParentSetMap)){
            return budgetValidIdSet;
        }else {
            for(Map.Entry<Long,Set<Long>> validAllParentSetEntry : validAllParentSetMap.entrySet()){
                Set<Long> entryValue = validAllParentSetEntry.getValue();
                if(entryValue.contains(budgetId)){
                    budgetValidIdSet = entryValue;
                    break;
                }
            }
        }
        return budgetValidIdSet;
    }

    /**
     * 获取年度预算项的生效id
     * @param year
     * @return
     */
    public Set<Long> getValidByYearInteger(Integer year){
        return budgetYearValidMap.get(year);
    }

    public Long getValidByYearAndBudgetId(Integer year,Long budgetId){
        //1、获取当前年度所有的预算项信息
        Set<Long> budgetValidIdSet = budgetYearValidMap.get(year);
        //2、循环所有预算项，判断预算项的上游单据是否存在
        for(Long budgetValidId : budgetValidIdSet){
            Set<Long> validAllParentSetMap = getValidAllParentSetMap(budgetValidId);
            if(validAllParentSetMap.contains(budgetId)){
                return budgetValidId;
            }
        }
        return 0L;
    }

    /**
     * 获取生效上游id集合
     * @param budgetId
     * @param validType
     * 生效类型：
     * true：查询生效上游，根据年度区分
     * false：生效上游，追溯全部上游
     * 举例：
     * 单据a  本单： id1  上游： id2  是否生效：是 年度：2023
     * 单据b  本单： id2  上游： id3  是否生效：否 年度：2023
     * 单据c  本单： id3  上游： id4  是否生效：是 年度：2024
     * 单据d  本单： id4  上游： id5  是否生效：否 年度：2023
     * 单据e  本单： id5  上游： id5  是否生效：否 年度：2023
     * 0：
     * 生效id: id1 上游id: id1,id2
     * 生效id: id3 上游id: id3,id4,id5
     * 1:
     * 生效id: id1 上游id: id1,id2,id3,id4,id5
     * 生效id: id3 上游id: id3,id4,id5
     * @return
     */
    public Set<Long> getBudgetValidId(Long budgetId,boolean validType){
        Set<Long> validIdSet;
        if(validType){
            validIdSet = getValidParentSetMap(budgetId);
        }else {
            validIdSet = getValidAllParentSetMap(budgetId);
        }
        return validIdSet;
    }

    public Long getBudgetValidId(Long budgetId,boolean validType,Integer year){
        Set<Long> budgetValidId = getBudgetValidId(budgetId, validType);
        //判断是否存在生效id
        Long validId = 0L;
        if(MapUtils.isEmpty(budgetYearValidMap)){
            return validId;
        }
        //获取本年度当前项目所有预算项id
        Set<Long> budgetYearValidSet = budgetYearValidMap.get(year);
        if(CollectionUtils.isNotEmpty(budgetYearValidSet)){
            //取两个集合的交集
            //取值原因：
            //budgetYearValidMap 中存放的是年度 + 当前年度的所有预算值，所有预算值唯一
            //budgetValidId 获取到的是生效id集合，预算项能获取的为所有
            for (Long budgetYearValidLong : budgetYearValidSet) {
                if(CollectionUtils.isNotEmpty(budgetValidId) && budgetValidId.contains(budgetYearValidLong)){
                    validId = budgetYearValidLong;
                    break;
                }
            }
        }
        return validId;
    }
}
